AngularJS路由系列(2)

您所在的位置:网站首页 angular history AngularJS路由系列(2)

AngularJS路由系列(2)

#AngularJS路由系列(2)| 来源: 网络整理| 查看: 265

 

本系列探寻AngularJS的路由机制,在WebStorm下开发。主要包括:

 

● 刷新路由● 查看当前路由以及所有路由● 路由触发事件● 获取路由参数

● 路由的resolve属性● 路由URL格式

 

AngularJS路由系列包括:

1、AngularJS路由系列(1)--基本路由配置2、AngularJS路由系列(2)--刷新、查看路由,路由事件和URL格式,获取路由参数,路由的Resolve3、AngularJS路由系列(3)-- UI-Router初体验4、AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数5、AngularJS路由系列(5)-- UI-Router的路由约束、Resolve属性、路由附加数据、路由进入退出事件6、AngularJS路由系列(6)-- UI-Router的嵌套State

 

项目文件结构

 

node_modules/

public/.....app/..........bower_components/...............toastr/....................toastr.min.css....................toastr.min.js...............jquery/....................dist/.........................jquery.min.js...............angular/....................angular.min.js...............angular-ui-router/....................release/.........................angular-ui-router.min.js...............angular-route/.........................angular-route.min.js..........controllers/...............HomeController.js...............AllSchoolsController.js...............AllClassroomsController.js...............AllActivityiesController.js...............ClassroomController.js...............ClassroomSummaryController.js...............ClassroomMessageController.js..........css/...............bootstrap.cerulean.min.css..........filters/...............activityMonthFilter.js..........services/...............dataServices.js...............notifier.js..........templates/...............home.html...............allSchools.html...............allClassrooms.html...............allActivities.html...............classroom.html...............classroomDetail.html...............classroom_parent.html..........app.js.....index.html.....favicon.icoserver/.....data/.....routes/.....views/.....helpers.jspackage.jsonserver.js

 

刷新路由

 

有时候我们需要刷新路由而不是整个页面。该如何做呢?ngRoute这个module为我们准备了$route服务的reload()方法可以实现。

 

■ HomeController.js, 添加刷新路由功能,$route.reload

 

(function(){ angular.module('app') .controller('HomeController',['dataService','notifier', '$route', '$log', HomeController]); function HomeController(dataService, notifier, $route, $log){ var vm = this; vm.message = 'Welcome to School Buddy!'; //重新刷新路由 vm.refresh = function(){ $route.reload(); } dataService.getAllSchools() .then(function(schools){ vm.allSchools = schools; vm.schollCount = schools.length; }) .catch(showError); dataService.getAllClassrooms() .then(function(classroom){ vm.allClassrooms = classrooms; vm.classroomCount = classrooms.length; }) .catch(showError); dataService.getAllActivities() then(function(activities)){ vm.allActivities = activities; vm.activityCount = activities.length; } ... } }());

 

■ home.html, 添加刷新路由的按钮

{{home.message}}{{home.schoolCount}}{{home.activityCount}}

刷新

 

当点击"刷新"按钮,刷新的只是路由,不是整个页面。

 

查看当前路由以及所有路由

 

$route服务提供了current和routes属性。

 

■ HomeController.js, 查看当前路由以及所有路由,使用$route的current和routes属性

 

(function(){ angular.module('app') .controller('HomeController',['dataService','notifier', '$route', '$log', HomeController]); function HomeController(dataService, notifier, $route, $log){ var vm = this; vm.message = 'Welcome to School Buddy!'; //重新刷新路由 vm.refresh = function(){ $log.debug($route.current); $log.debut($route.routes); $route.reload(); } dataService.getAllSchools() .then(function(schools){ vm.allSchools = schools; vm.schollCount = schools.length; }) .catch(showError); dataService.getAllClassrooms() .then(function(classroom){ vm.allClassrooms = classrooms; vm.classroomCount = classrooms.length; }) .catch(showError); dataService.getAllActivities() then(function(activities)){ vm.allActivities = activities; vm.activityCount = activities.length; } ... } }());

 

$route.current相关的如下:

 

$route.routes相关如下:

 

路由触发事件

 

$route服务提供以下几个事件:

● $routeChangeStart ● $routeChangesSuccess● $routeChangeError● $routeUpdate使用$on来调用事件

 

这些事件是在路由发生变化、路由成功、路由异常、路由更新时被触发。谁来做这些事件的载体呢?我们可以使用$on方法把这些事件注册到$rootScope上去,这样,在全局范围内触发这些事件。

 

■ app.js,为$rootScope添加路由事件

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', function($logProvider,$routeProvider){ $logProvider.debugEnabled(true); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html', resolve:{ promise: function(){ throw 'error transitioning to classrooms'; } } }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

以上,使用resolve在controller初始化之前定义一个promise方法故意抛出一个异常。

在localhost:3000/#/下刷新浏览器,即触发了$rootScope的$routeChangeSuccess事件。

 

可见,event用来存放当前触发事件;current用来存放当前路由,previous用来存放上一个路由。

 

清空控制台记录,点击导航栏上的Activities

 

previous显示了上一个路由。

 

清空控制台记录,点击导航栏上的Classroom,即我们故意在该路由中设置了一个异常。

 

获取路由参数

 

有时候我们需要获取路由中的参数,ngRoute为我们提供了$routeParams服务。

 

.when('/classrooms/:id',{

})

 

在控制器中大致这样:

 

function ClassroomController($routeParams){ var classroomID = $routeParams.id; //使用classroomID获取相关Classroom }

 

■ app.js,针对Classroom添加一个带参数的路由

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', function($logProvider,$routeProvider){ $logProvider.debugEnabled(true); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html' }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html' }) .when('/classrooms/:id',{ templateUrl: '/app/templates/classroom.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

■ ClassroomController.js

 

(function(){ angular.module('app',[]) .controller('ClassroomController', ['dataService','notifier', '$routeParams', ClassroomController]); function ClassroomController(dataService, notifier, $routeParams){ var vm = this; dataService.getClassroom($routeParams.id) .then(function(classroom){ vm.currentClassroom = classroom; }) .catch(showError); function showError(message){ notifier.error(message); } } }());

 

在浏览器中输入localhost:3000/#/classrooms/1

 

■ app.js,针对Classroom添加带更多参数的路由

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', function($logProvider,$routeProvider){ $logProvider.debugEnabled(true); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html' }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html' }) .when('/classrooms/:id',{ templateUrl: '/app/templates/classroom.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .when('/classroom/:id/detail/:month?',{ templateUrl: '/app/templates/classroomDetail.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

■ ClassroomController.js

 

(function(){ angular.module('app',[]) .controller('ClassroomController', ['dataService','notifier', '$routeParams', ClassroomController]); function ClassroomController(dataService, notifier, $routeParams){ var vm = this; vm.month = $routeParams.month; dataService.getClassroom($routeParams.id) .then(function(classroom){ vm.currentClassroom = classroom; //判断路由中是否有month这个参数 if($routeParams.month){ //集合或数组是否为空 if(classroom.activities.length > 0){ vm.timePeriod = dataService.getMonthName($routeParams.month); } else { vm.timePeriod = 'No activities this month'; } } else { vm.timePeriod = 'All activities'; } }) .catch(showError); function showError(message){ notifier.error(message); } } }());

 

■ AllActivitiesController.js

 

(function(){ angular.module('app') .controller('AllActivitiesController', ['dataService', 'notifier', '$location', AllActivitiesController]); function AllActivitiesController(dataService, notifier, $location){ var vm = this; vm.seletedMonth = 1; //搜索过滤 vm.search = function(){ var classroom_detail_url = '/classrooms/' + vm.selectedClassroom.id + '/detail/' +vm.seletedMonth; $location.url(classroom_detail_url); }; dataService.getAllClassrooms() .then(function(classrooms){ vm.allClassrooms = classroom; vm.seletedClassroom = classrooms[0]; }) .catch(showError); dataService.getAllActivities() .then(function(activities)){ vm.allActivities = activities; } .catch(showError); function showError(message){ notifier.error(message); } } }());

 

可见,使用$location.url(route)方法可以轻松转到任何路由。

 

路由的Resolve属性

 

在配置路由的时候有一个Resolve属性,接受一个Object对象,对象的每一个属性接收一个函数,resolve中的事件发生在controller初始化之前,最终也将被注入到controller中。

 

.when('/activities', { controller: 'AllActivitiesController', controllerAd: 'activities', templateUrl: '/app/tempaltes/allActivities.html', resolve: { activities: function(dataService){ return dataService.getAllActivities(); } } })

 

以上,dataService.getAllActivities方法返回一个promise,必须要被resolved之后才会转到相应的视图页。接着,activities可以被注入到AllActivitiesController中。

 

■ app.js, 在/activities路由下加上resolve属性

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', function($logProvider,$routeProvider){ $logProvider.debugEnabled(true); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html' }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html', resolve: { activities: function(dataService){ return dataService.getAllActivites(); } } }) .when('/classrooms/:id',{ templateUrl: '/app/templates/classroom.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .when('/classroom/:id/detail/:month?',{ templateUrl: '/app/templates/classroomDetail.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

■ AllActivitiesController.js,把路由resolve属性中的activities注入到控制器中来

 

(function(){ angular.module('app') .controller('AllActivitiesController', ['dataService', 'notifier', '$location', 'activities', AllActivitiesController]); function AllActivitiesController(dataService, notifier, $location, activities){ var vm = this; vm.seletedMonth = 1; //这里的activites中路由的resolve中来 //原先的getAllActivities方法就不需要存在了 vm.allActivities = actvities; //搜索过滤 vm.search = function(){ var classroom_detail_url = '/classrooms/' + vm.selectedClassroom.id + '/detail/' +vm.seletedMonth; $location.url(classroom_detail_url); }; dataService.getAllClassrooms() .then(function(classrooms){ vm.allClassrooms = classroom; vm.seletedClassroom = classrooms[0]; }) .catch(showError); function showError(message){ notifier.error(message); } } }());

 

使用resolve的好处是:当视图页向$scope要数据的时候,由于在controller实例化之前已经准备好了数据,所以页面延迟时间大大缩短。

 

路由URL格式

 

● Hashbang格式: localhost:3000/#/classrooms/1/detail/12,默认的就是这种格式● HTML5格式:localhost:3000/classrooms/1/detail/12,需要使用$locationProvider配置,如果使用这种格式,但浏览器不支持HTML5的历史API,Angular就会使用Hashbang格式。

 

■ app.js, 引用$locationProvider配置自定义url格式

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', '$locationProvider', function($logProvider,$routeProvider, $locationProvider){ $logProvider.debugEnabled(true); //使用自定义url格式 $locationProvider.hasPrefix('!'); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html' }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html', resolve: { activities: function(dataService){ return dataService.getAllActivites(); } } }) .when('/classrooms/:id',{ templateUrl: '/app/templates/classroom.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .when('/classroom/:id/detail/:month?',{ templateUrl: '/app/templates/classroomDetail.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

■ index.html,为了配合以上的自定义url格式需要做些改变

 

School Buddy Schools Classrooms Activities

 

 

■ app.js, 引用$locationProvider配置HTML5的url格式

 

(function(){ var app = angular.module('app', ['ngRoute']); app.config(['$logProvider','$routeProvider', '$locationProvider', function($logProvider,$routeProvider, $locationProvider){ $logProvider.debugEnabled(true); //使用HTML5格式 $locationProvider.html5Mode({ enabled: true, requireBase: true, //需要配置基地址 rewriteLinks: true //遇到旧版本的浏览器会使用默认的Hashbang模式 }); $routeProvider .when('/',{ controller: 'HomeController' , controllerAs: 'home', templateUrl: '/app/templates/home.html' }) .when('/schools',{ controller: 'AllSchoolsController', controllerAs: 'schools', templateUrl: '/app/templates/allSchools.html', caseInsensitiveMatch: true }) .when('/classrooms/:id',{ controller: 'AllClassroomsController', controllerAs: 'classrooms', templateUrl: '/app/templates/allClassrooms.html' }) .when('/activities',{ controller: 'AllActivitiesController', controllerAs: 'activities', templateUrl: '/app/templates/allActivities.html', resolve: { activities: function(dataService){ return dataService.getAllActivites(); } } }) .when('/classrooms/:id',{ templateUrl: '/app/templates/classroom.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .when('/classroom/:id/detail/:month?',{ templateUrl: '/app/templates/classroomDetail.html', controller: 'ClassroomController', controllerAs: 'classroom' }) .otherwise('/'); }]); app.run(['$rootScope', '$log', function($rootScope, $log){ //通过$on为$rootScope添加路由事件 $rootScope.$on('$routeChangeSuccess',function(event, current, previous){ $log.debug('successfully changed routes'); $log.debug(event); $log.debug(current); $log.debug(previous); }); $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){ $log.debug('error changing routes'); $log.debug(event); $log.debug(current); $log.debug(previous); $log.debug(rejection); }); }]); }());

 

■ index.html,为了配合URL的HTML5格式需要做些改变

 

School Buddy Schools Classrooms Activities

 

但是url使用HTML5格式有一个不好的地方,当输入一个不存在的url就会报一个404的错。

 

 

未完待续~~

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3